#include "m_camera.h"
#include <iostream>
using namespace std;
using namespace glm;

Camera &Camera::getinstance(float viewportx, float viewporty)
{
    static bool inited = false;
    if (!inited && (viewportx < 0 || viewporty < 0))
    {
        cout << "Error: Please provide the viewport size!" << endl;
        exit(-1);
    }
    static Camera instance(viewportx, viewporty);
    inited = true;
    return instance;
}

Camera::Camera(float viewportx,
               float viewporty,
               glm::vec3 pos,
               glm::vec3 front,
               glm::vec3 up) : viewportx(viewportx),
                               viewporty(viewporty),
                               _pos(pos),
                               _front(front),
                               _up(up),
                               yaw(-90.0f),
                               fov(45.0f) {}

void Camera::mouseMove(float sens, float xoff)
{
    xoff *= sens;
    yaw += xoff;
    if (yaw > -1.0f)
        yaw = -1.0f;
    if (yaw < -179.0f)
        yaw = -179.0f;
    vec3 frt = vec3(1.0f);
    frt.x = cos(radians(yaw));
    frt.y = 0.0f;
    frt.z = sin(radians(yaw));
    _front = normalize(frt);
}

void Camera::reset()
{
    _pos = vec3(0.0, 0.0, 3.0);
    _front = vec3(0.0, 0.0, -1.0);
    _up = vec3(0.0, 1.0, 0.0);
    yaw = -90.0f;
    fov = 45.0f;
}

mat4 Camera::projection() const
{
    return perspective(radians(fov), (float)viewportx / viewporty, 0.1f, 100.0f);
}

mat4 Camera::view() const
{
    return lookAt(_pos, _pos + _front, _up);
}

vec3 Camera::Position() const
{
    return _pos;
}
vec3 Camera::front() const
{
    return _front;
}
vec3 Camera::up() const
{
    return _up;
}